#include "ImagePlayEngine.h"
#include "MainFrame.h"

wxDEFINE_EVENT(EVT_PLAY_ENGINE, wxCommandEvent);

ImagePlayEngine::ImagePlayEngine(wxWindow* parent,int _wxID,SaveFile* _fileControl, ImageDisplay* _display, wxSlider* _playSlider) :
	fileControl(_fileControl),display(_display),playSlider(_playSlider),frameRate(30),parentHandle(parent),wxID(_wxID)
{
}

ImagePlayEngine::~ImagePlayEngine()
{
	if(!FileReadThread.joinable()) return;
	if(PlayStatus.load())
		Pause();
	ThreadExitFlag.store(true);
	FromPauseWake.notify_all();
	std::lock_guard lck(PlayLCK);  //只要线程退出了，这里就能获得锁
}

void ImagePlayEngine::Reset(std::string fileName)
{
	if(fileName.length()==0) return;
	if(PlayStatus.load()) Pause();
	std::lock_guard lck(PlayLCK);
	fileControl->StopReadImage();
	fileControl->StartReadImage(fileName, width, height, frameCount,ImageFormat);
	playSlider->SetRange(0,frameCount - 1);
	playSlider->SetValue(0);
	playPos = 0;
}

void ImagePlayEngine::on_Timeout(wxTimerEvent& event)
{
	try
	{
		unsigned char* imgData=fileControl->ReadImage();
		display->showImage(imgData, width, height,ImageFormat);
		delete [] imgData;
		playPos++;
		playSlider->SetValue(playPos);
	}
	catch (const int e)
	{
		PlayFinishHandle(PlayFinishUserData);
	}
}

void ImagePlayEngine::SetPos(long pos)
{
	Pause();
	std::lock_guard lck(PlayLCK);
	playPos.store(pos);
	fileControl->SetFramePos(playPos);
	unsigned char* imgData=fileControl->ReadImage();
	display->showImage(imgData, width, height,ImageFormat);
	delete [] imgData;
}

void ImagePlayEngine::Play()
{
	if(PlayStatus.load()) return; //如果已经开始播放了
	PlayStatus.store(true);
	if(FileReadEOF.load()) //说明线程跑路了
	{
		FileReadEOF.store(false);
		FileReadThread.join(); //回收线程
		Reset(fileControl->GetCurrentFileName());
	}
	if(!FileReadThread.joinable()) //线程没有启动
		FileReadThread=std::thread(&ImagePlayEngine::FileReadFun,this);
	else
		FromPauseWake.notify_one(); //叫醒播放线程
}

void ImagePlayEngine::Pause()
{
	PlayStatus.store(false);
}

void ImagePlayEngine::SetFrameRate(unsigned _frameRate)
{
	frameRate.store(_frameRate);
}

long ImagePlayEngine::GetAllFrame()
{
	return frameCount;
}

long ImagePlayEngine::GetPos()
{
	return playPos;
}

void ImagePlayEngine::SetPlayFinishHandle(std::function<void(void*)> func, void* userData)
{
	PlayFinishHandle = func;
	PlayFinishUserData = userData;
}

bool ImagePlayEngine::IsPlay()
{
	return PlayStatus.load();
}

std::string ImagePlayEngine::GetFileName()
{
	return fileControl->GetCurrentFileName();
}

void ImagePlayEngine::FileReadFun()
{
	std::unique_lock lck(PlayLCK);
	while(!ThreadExitFlag.load())
	{
		if(PlayStatus.load())
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(1000/frameRate.load()));
			try
			{
				unsigned char* imageData=fileControl->ReadImage();
				display->showImage(imageData, width, height,ImageFormat);
				delete [] imageData;
			}
			catch(...)
			{
				PlayStatus.store(false);
				FileReadEOF.store(true);
				((MainFrame*)parentHandle)->emitPlayEngineFinish();
				return;
			}
			playPos++;
		}
		else
		{
			FromPauseWake.wait(lck);
		}
	}
}
